package net.grandcentrix.thirtyinch.sample.fragmentlifecycle;

import net.grandcentrix.thirtyinch.sample.ResourceTable;
import net.grandcentrix.thirtyinch.TiConfiguration;
import net.grandcentrix.thirtyinch.TiFragment;
import net.grandcentrix.thirtyinch.TiLog;
import net.grandcentrix.thirtyinch.util.BackstackReader;
import ohos.aafwk.ability.fraction.Fraction;
import ohos.aafwk.ability.fraction.FractionAbility;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Text;
import ohos.app.Context;
import rx.subjects.PublishSubject;

import java.util.UUID;


public abstract class TestFragment extends TiFragment<TestPresenter, TestPresenter.TestView> implements TestPresenter.TestView {
    final static String RETAIN_PRESENTER = "retain";
    static int testFragmentInstanceCount = -1;

    private String TAG = this.getClass().getSimpleName() + "@" + Integer.toHexString(this.hashCode());

    private int instanceNum = Integer.MIN_VALUE;

    private PublishSubject<Boolean> addedState = PublishSubject.create();

    private PublishSubject<Boolean> detachedState = PublishSubject.create();

    private PublishSubject<Boolean> inBackStackState = PublishSubject.create();

    private PublishSubject<Boolean> isActivityChangingConfigState = PublishSubject.create();

    private PublishSubject<Boolean> isActivityFinishingState = PublishSubject.create();

    private PublishSubject<Boolean> removingState = PublishSubject.create();

    private String uuid = null;

    protected abstract int getLayoutResId();

    {
        TiLog.v(TAG, this.toString() + " constructor called");
        testFragmentInstanceCount++;
        instanceNum = testFragmentInstanceCount;
    }

    void onAttach(Context context) {
        addedState.startWith(false).distinctUntilChanged().skip(1)
                .subscribe(
                        added -> TiLog.d(TAG, "fragment" + instanceNum + ".setAdded(" + added + ")")
                );
        detachedState.startWith(false).distinctUntilChanged().skip(1)
                .subscribe(
                        detached -> TiLog.d(TAG, "fragment" + instanceNum + ".setDetached(" + detached + ")")
                );
        removingState.startWith(false).distinctUntilChanged().skip(1)
                .subscribe(
                        removing -> TiLog.d(TAG, "fragment" + instanceNum + ".setRemoving(" + removing + ")")
                );
        inBackStackState.startWith(false).distinctUntilChanged().skip(1)
                .subscribe(
                        inBackstack -> TiLog.d(TAG, "fragment" + instanceNum + ".setInBackstack(" + inBackstack + ")")
                );

        isActivityChangingConfigState.startWith(false).distinctUntilChanged().skip(1)
                .subscribe(
                        changing ->
                                TiLog.d(TAG,
                                        "hostingActivity" + FragmentLifecycleActivity.fragmentLifecycleActivityInstanceCount + ".setChangingConfiguration(" + changing + ");")
                );
        isActivityFinishingState.startWith(false).distinctUntilChanged().skip(1)
                .subscribe(
                        finishing ->
                                TiLog.d(TAG, "hostingActivity" + FragmentLifecycleActivity.fragmentLifecycleActivityInstanceCount + ".setFinishing(" + finishing + ");")
                );

        printState();
        TiLog.v(TAG, "onAttach(" + context + ")");
        printState();
    }

    @Override
    public void onStart(Intent intent) {
        printState();
        super.onStart(intent);
        TiLog.v(TAG, "onCreate(" + intent + ")");
        printState();
        if (intent != null) {
            uuid = intent.getStringParam("uuid");
            TiLog.v(TAG, "RESTORED " + uuid);
        }
        if (uuid == null) {
            uuid = UUID.randomUUID().toString();
            TiLog.v(TAG, "CREATED " + uuid);
        }

        if (intent == null) {
            TiLog.d(TAG, "fragment" + instanceNum + ".onCreate(null);");
        } else {
            TiLog.d(TAG, "fragment" + instanceNum + ".onCreate(savedInstanceState);");
        }
        onAttach(getContext());
    }


    @Override
    public Component onComponentAttached(LayoutScatter inflater, ComponentContainer container,
                                         Intent savedInstanceState) {
        super.onComponentAttached(inflater, container, savedInstanceState);
        printState();
        TiLog.v(TAG,
                "onCreateView() called with: inflater = [" + inflater + "], container = [" + container + "], savedInstanceState = [" + savedInstanceState + "]");
        if (savedInstanceState == null) {
            TiLog.d(TAG, "fragment" + instanceNum + ".onCreateView(inflater, null, null);");
        } else {
            TiLog.d(TAG, "fragment" + instanceNum + ".onCreateView(inflater, null, savedInstanceState);");
        }

        Component component = inflater.parse(getLayoutResId(), container, false);
        onViewCreated(component, savedInstanceState);
        return component;
    }

    void onViewCreated(Component view, Intent savedInstanceState) {
        printState();
        TiLog.v(TAG, "onViewCreated");
        printState();

        Text fragmentTag = (Text) view.findComponentById(ResourceTable.Id_sample_text);
        fragmentTag.setText(TAG);
    }

    @Override
    public void onForeground(Intent intent) {
        printState();
        super.onForeground(intent);
        TiLog.d(TAG, "fragment" + instanceNum + ".onStart();");
        printState();
    }

    @Override
    protected void onActive() {
        printState();
        super.onActive();
        TiLog.v(TAG, "onResume");
        printState();
    }

    @Override
    protected void onInactive() {
        printState();
        super.onInactive();
        TiLog.v(TAG, "onPause()");
        printState();
    }

    @Override
    public void onBackground() {
        printState();
        super.onBackground();
        TiLog.d(TAG, "fragment" + instanceNum + ".onStop();");
        printState();
    }

    @Override
    public void onStop() {
        printState();
        super.onStop();
        TiLog.v(TAG, "onDestroy");
        TiLog.d(TAG, "fragment" + instanceNum + " .onDestroy();");
        printState();
        TiLog.v("FragmentManager", "DESTROYED" + uuid);
        onDetach();
    }

    protected void onDetach() {
        printState();
        TiLog.v(TAG, "onDetach");
        printState();

        addedState.onCompleted();
        detachedState.onCompleted();
        removingState.onCompleted();
        isActivityChangingConfigState.onCompleted();
        isActivityFinishingState.onCompleted();
    }

    @Override
    public TestPresenter providePresenter() {

        boolean retain = false;

        TiConfiguration config = new TiConfiguration.Builder()
                .setRetainPresenterEnabled(retain)
                .build();

        TestPresenter presenter = new TestPresenter(config, getClass().getSimpleName());
        TiLog.d(TAG, "created " + presenter);
        TiLog.v(TAG, "retain presenter " + retain + ", " + presenter);

        return presenter;
    }

    protected void finalize() {
        TiLog.v(TAG, "GCed " + this + ", uuid: " + this.uuid);
    }

    private void printState() {
        inBackStackState.onNext(BackstackReader.isInBackStack(this));

        FractionAbility ability = getFractionAbility();
        if (ability == null) {
            return;
        }
    }
}
